package com.terracloud.server.common.data.tree;

import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Predicate;

/**
 *
 * @author chenhainan
 * @since 2025/10/17
 */
public class TreeUtil {

    private TreeUtil() {
    }

    public static <T extends TreeNode<T, ID>, ID> List<T> buildTree(List<T> nodes) {
        return buildTree(nodes, treeNode -> treeNode.getPId() == null);
    }

    public static <T extends TreeNode<T, ID>, ID> List<T> buildTree(List<T> nodes,
                                                                    Predicate<T> topConditionFilter) {
        return buildTree(nodes, topConditionFilter, (tidTreeNode1, tidTreeNode2) -> tidTreeNode1.getId().equals(tidTreeNode2.getPId()));
    }

    public static <T extends TreeNode<T, ID>, ID> List<T> buildTree(List<T> nodes,
                                                                    Predicate<T> topConditionFilter,
                                                                    BiPredicate<T, T> childConditionFilter) {
        return nodes.stream()
                .filter(topConditionFilter)
                .map(topNode -> buildTree(nodes, topNode, childConditionFilter))
                .toList();
    }

    public static <T extends TreeNode<T, ID>, ID> T buildTree(List<T> nodes,
                                                              T topNode,
                                                              BiPredicate<T, T> childConditionFilter) {
        for (var node : nodes) {
            if (childConditionFilter.test(topNode, node)) {
                topNode.getChildren().add(buildTree(nodes, node, childConditionFilter));
            }
        }
        return topNode;
    }

}
